`timescale 1ns / 1ps
`define SCANLENGTH 1105
////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer:
//
// Create Date:   00:37:16 03/11/2010
// Design Name:   RAM_ctrl
// Module Name:   F:/RAMCtrl/CellRAMController/RAM_ctrl_tb.v
// Project Name:  CellRAMController
// Target Device:  
// Tool versions:  
// Description: 
//
// Verilog Test Fixture created by ISE for module: RAM_ctrl
//
// Dependencies:
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
////////////////////////////////////////////////////////////////////////////////

module RAM_ctrl_tb;

	// Inputs
	reg clk;
	reg reset;
	reg mem;
	reg rw;
	reg [22:0] address;
	reg [15:0] data_fpga2ram;
	wire o_wait;

	// Outputs
	wire ready;
	wire [15:0] data_ram2fpga_r;
	wire [15:0] data_ram2fpga_ur;
	wire [22:0] addr;
	wire we_n;
	wire oe_n;
	wire ce_n;
	wire ub_n;
	wire lb_n;
	wire clock_ram;
	wire adv_n;
	wire cre;

	// Bidirs
	wire [15:0] dio;
	
	//state parameters
	localparam [1:0] IDLE = 2'b00, READ = 2'b01, WRITE = 2'b10;
	
	wire PS1, PS2, PS3;
	//clock generator module
	clock_generator clock_gen (
		.clock_in(clk), 
		.reset(reset), 
		.clock_PS1(PS1), 
		.clock_PS2(PS2), 
		.clock_PS3(PS3), 
		.clock8(), 
		.clk16(clk16), //we only use the 16Mhz clock in thsi test
		.clock50()
	);
	
	// Instantiate the Unit Under Test (UUT)
	RAM_ctrl uut (
		.clk(clk16), 
		.reset(reset), 
		.mem(mem), 
		.rw(rw), 
		.address(address), 
		.data_fpga2ram(data_fpga2ram), 
		.ready(ready), 
		.data_ram2fpga_r(data_ram2fpga_r), 
		.data_ram2fpga_ur(data_ram2fpga_ur), 
		.addr(addr), 
		.dio(dio), 
		.we_n(we_n), 
		.oe_n(oe_n), 
		.ce_n(ce_n), 
		.ub_n(ub_n), 
		.lb_n(lb_n), 
		.clock_ram(clock_ram), 
		.adv_n(adv_n), 
		.cre(cre), 
		.o_wait(o_wait)
	);
	
	//We instantiate the RAM model to test the controller's operation
	cellram cellRAM (
        .clk    (clock_ram),
        .adv_n  (adv_n),
        .cre    (cre),
        .o_wait (o_wait),
        .ce_n   (ce_n),
        .oe_n   (oe_n),
        .we_n   (we_n),
        .ub_n   (ub_n),
        .lb_n   (lb_n),
        .addr   (addr),
        .dq     (dio)
    );
	
	localparam tPU = 150e3;

   task power_up;
        begin
            clk   = 1'b0;            
            address = 0;
				reset = 1;
				mem = 0;
				rw = 0;
            #(tPU)
				reset = 0;
        end
    endtask	

    task write;
        input [22:0] wr_addr;
        input [15:0] wr_data;
        begin
            rw  = 1'b0;//assert a write operation
			while(!ready) mem = 0;//wait for the RAM ctrl to be ready
						
			address = wr_addr;
			@(posedge clk16) mem = 1'b1;
			@(posedge clk16) mem = 0;
        end
    endtask
	
	task read;
        input [22:0] rd_addr;
        output [15:0] rd_data;		
        begin
            rw  = 1'b1;//assert a write operation
			while(!ready) mem = 0;//wait for the RAM ctrl to be ready
			
			
			address = rd_addr;
			@(posedge clk16) mem = 1'b1;
			@(posedge clk16) mem = 0;
			while(~ready) rd_data = data_ram2fpga_r;
        end
    endtask

	integer counter, i;
	
	reg [15:0] read_data;
	reg [5:0] pixel;
	reg sync;
	reg scanstart;
	reg valid_pixel;

reg [22:0] pixel_counter;
reg coupon;
		
wire get_pixel;
reg mem_reg, mem_next;
reg [22:0] mem_addr_reg, mem_addr_next;		
		
		
initial begin
		// Initialize Inputs
		power_up;

		scanstart = 1'b1;
		sync = 1'b1;
		coupon = 1'b0;
		counter = `SCANLENGTH;
		pixel = 6'b0;
		valid_pixel = 1'b0;
        
		// Add stimulus here
		for(i = 0; i < 10; i = i+1) begin 
			@(posedge valid_pixel)
			address = i;
			@(posedge PS1) //new pixel at PS3, latch pixel at PS1, write pixel to memory at PS2
			rw = 0;
			mem = 1;
			@(posedge clk16)
			mem = 0;
			rw = 1;
			
			@(posedge ready)
			@(posedge clk16)
			rw = 1;
			mem = 1;
			@(posedge clk16)
			mem = 0;
			
		end	
		
		//#100
		
		//@(posedge clk16)
		//rw = 1;
		//mem = 1;
		//@(posedge clk16)
		//mem = 0;
		
		#100
		
		$stop();
	end
	
	//clockgenerator
	always #10 clk = ~clk;//50Mhz clock		
	
//random pixel generator	
	always @(posedge PS3) begin
	pixel <= $random;
	valid_pixel <= 1;
	end

always @(negedge PS3) valid_pixel <= 0;

//sync interrupt
	always @ (negedge sync)
	begin
		pixel_counter <= 0;
		coupon <= 1;
	end			

//scanstart logic
always @ (posedge PS3)
	if(counter == 0) begin
		scanstart <= 1'b0;
		counter <= `SCANLENGTH;
	end else begin
		scanstart <= 1'b1;
		counter <= counter - 1;
	end	

always @(posedge PS1)
	data_fpga2ram <= {10'b0, pixel};

endmodule

